//
//  DebugNetWorkSaveUtil.m
//  YK_DebugManager
//
//  Created by edward on 2021/3/25.
//

#import "DebugNetWorkSaveUtil.h"
#import "DebugNetWorkManager.h"

@interface DebugNetWorkSaveUtil ()<NSStreamDelegate>

@property (nonatomic, copy) void(^bodyCallBack)(NSData *);

@property (nonatomic, strong) NSMutableData *bodyData;

@end

@implementation DebugNetWorkSaveUtil

static DebugNetWorkSaveUtil *_instance;

+ (id)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });

    return _instance;
}

+ (instancetype)sharedInstance
{
    if (_instance == nil) {
        _instance = [[DebugNetWorkSaveUtil alloc] init];
    }
    return _instance;
}

- (void)save:(NSURLRequest *)request response:(NSURLResponse *)response startTime:(NSDate *)startTime data:(NSMutableData *)data
{
    DebugNetWorkModel *record = [[DebugNetWorkModel alloc] init];
    record.request = request;
    record.response = response;
    NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
    record.statusCode = [NSString stringWithFormat:@"%d",(int)httpResponse.statusCode];
    record.startTime = startTime;
    record.endTime = [NSDate date];
    record.url = request.URL.absoluteString?:@"";
    record.method =request.HTTPMethod?:@"";
    record.allHttpHeader = request.allHTTPHeaderFields?:@{};
    record.mineType = response.MIMEType?:@"";
    record.responseData = data;
    
    
    __weak typeof(record) weakrecord = record;
    [self getBody:request block:^(NSData *body) {
        __strong typeof(weakrecord) strongrecord = weakrecord;
        strongrecord.requestBody = body;
    }];
    [[DebugNetWorkManager sharedInstance] saveRecord:record];
}

- (void)getBody:(NSURLRequest *)request block:(void(^)(NSData *body))block
{
//    record.requestBody = self.request.HTTPBody;
    NSData *httpBody = nil;
    if (request.HTTPBody) {
        httpBody = request.HTTPBody;
        block(httpBody);
        return;
    }
    if ([request.HTTPMethod isEqualToString:@"POST"]) {
        NSInputStream *stream = request.HTTPBodyStream;
        [stream setDelegate:self];
        self.bodyCallBack = block;
        [stream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [stream open];
    } else {
        block(httpBody);
    }
}

#pragma mark -- NSStreamDelegate
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
    switch (eventCode) {
        case NSStreamEventHasBytesAvailable:
        {
            if (!self.bodyData) {
                self.bodyData = [NSMutableData data];
            }
            uint8_t buf[1024];
            NSInteger len = 0;
            len = [(NSInputStream *)aStream read:buf maxLength:1024];
            if (len) {
                [self.bodyData appendBytes:(const void *)buf length:len];
            }
        }
            break;
        case NSStreamEventErrorOccurred:
        {
            NSError * error = [aStream streamError];
            NSString * errorInfo = [NSString stringWithFormat:@"Failed while reading stream; error '%@' (code %ld)", error.localizedDescription, error.code];
            NSLog(@"%@",errorInfo);
        }
            break;
        case NSStreamEventEndEncountered:
        {
            [aStream close];
            [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            aStream = nil;
            if (self.bodyCallBack) {
                self.bodyCallBack([self.bodyData copy]);
            }
            self.bodyData = nil;
        }
            break;
        default:
            break;
    }
}

@end
